package org.model.modbus;

import org.MonitorPantalla;
import org.model.data.Configuration;
import org.model.data.DataManager;
import org.model.data.Device;
import org.util.DateFormatter;
import org.util.SerialPort;
import org.util.Util;
import java.util.Calendar;

/**
 *
 * @author German garcia
 */
public class ModbusManager implements Runnable {
    private MonitorPantalla gsmMobile;
    private boolean running;

    private SerialPort serialPort = null;
	//private GSMModbusRTUTransport serialTransport;
    private GSMModbusSerialTransaction serialTransaction;

    //Operational attributes
    private DataManager dms;
    private DataManager dmd;
    private boolean isTimeToSave;
    private boolean isTimeToReset;
	//private boolean isTimeToSendData;
    //private Device[] glesToUpdate;
    private Device[] devices;
    private Device device;
    private Calendar time;
    private int lastSaved;
    private int currentSave;
    private int updateTime;
    private String[] dataFrame;
    private String datetime;
    private String type;

    public ModbusManager(MonitorPantalla gsmMobile) {
        this.gsmMobile = gsmMobile;
 
        dms = null;
        dmd = null;
        running = false;
        try {
            dms = DataManager.getInstance(DataManager.SETUP_CATALOG);
            dmd = DataManager.getInstance(DataManager.DEVICES_CATALOG);

            //1. Load parameters
            Configuration configuration = dms.readConfiguration();
            devices = dmd.listDevices();
            dataFrame = new String[devices.length];
            //glesToUpdate = null;

            //2. Setup serial parameters
            //3. Open the connection
            initializeCOMPort(configuration);
            this.gsmMobile.setCurrentStatus("Puerto Serial Connectado.");
            //4. Set master identifier
            //5. Prepare the transaction
            //serialTransaction = new GSMModbusSerialTransaction(serialPort, serialTransport = new GSMModbusRTUTransport());
            serialTransaction = new GSMModbusSerialTransaction(serialPort, new GSMModbusRTUTransport());
            serialTransaction.setTransDelayMS(500);
            serialTransaction.setRetries(3);

            // Operational attributes initialization
            isTimeToSave = false;
            //isTimeToReset = false;
            //isTimeToSendData = false;
            device = null;
            time = null;
            lastSaved = -1;
            currentSave = -2;
            //System.out.println("Refresh: " + configuration.getRefresh());
            //System.out.println("Refresh splitted: " + Util.split(configuration.getRefresh(), " ")[0]);
            updateTime = Integer.parseInt(Util.split(configuration.getRefresh(), " ")[0]);
            datetime = "";
            type = "";

            //System.out.println(sdf.format(Calendar.getInstance().getTime()));
            //dms.releaseInstance();
        } catch(Exception ex) {
            if(dms.isValid()) dms.releaseInstance();
            ex.printStackTrace();
        }
    }
    public void setRunning(){
        running = true;
    }
        
    public synchronized void run() {
        int i=0;     
        //gsmMobile.updateTime();
        while(running){
        //if (running) {

        	try {
                gsmMobile.updateTime();
        		Thread.sleep(1000);

                isTimeToSave = false;
                isTimeToReset = false;
                // Verificamos si se debe guardar el siguiente dato
                //time = new Time();
                time = Calendar.getInstance();
                datetime = DateFormatter.format(time, true);
                System.out.println(updateTime);
                if (time.get(Calendar.MINUTE) == 3) isTimeToReset = true;
                if ((time.get(Calendar.MINUTE) == 0) || (time.get(Calendar.MINUTE) % updateTime) ==0) {
                    currentSave = time.get(Calendar.MINUTE);
                    if(lastSaved!=currentSave) {
                        lastSaved = currentSave;
                        isTimeToSave = true;
                        datetime = DateFormatter.format(Calendar.getInstance(), false);
                    }
                }
                if(isTimeToSave) {
                    //gsmMobile.setStopVisible(false);
                    //gsmMobile.repaintNow();
                    //dmd.clearGlesData();
                    //isTimeToSendData = true;

                    //6. Loop the devices and read data
                    gsmMobile.clearText();
                    gsmMobile.setCurrentMessage("Leyendo datos... Por favor espere!");
                    //gsmMobile.addLog("Retrieving data... Please wait!");
                    for(i=0; i<devices.length; i++) {
                        dataFrame[i] = "";
                        device = devices[i];
                        //7. Prepare the requests
                        //8. Execute the transactions
                        // Set the message for the current capture
                        type = device.getType()==0 ? "GLES " : "METER "; //if instanceof Gles
                        // Capture the device data
                        gsmMobile.setCurrentMessage("Leyendo " + type + " " + device.getName());
                        //if instanceof Gles
                        if(device.getType()==0) dataFrame[i] = MemoryMapManager.read(device, datetime, serialTransaction);
                        else dataFrame[i] = MemoryMapManager.read(device, datetime, serialTransaction);
                        // Check if there where errors on the procces
                        if(dataFrame[i].length()>0) {
                            if(dataFrame[i].length()==0 || Util.split(dataFrame[i], ",")[0].equals("error")) {
                                gsmMobile.setCurrentMessage(type + " " + device.getName() + " isn't available");
                            } else {
                                gsmMobile.setCurrentMessage(type + " " + device.getName() + " is OK");
                                // Mostrar VAvg y CAvg
                            }
                        }
                        System.out.println("index: " + i);
                        System.out.println("155-ModbusManager - data: " + dataFrame[i]);
                        gsmMobile.setCurrentMessage("datos: " + dataFrame[i]);
                    }
                    System.out.println("Conectando a servidores...");                   
                    gsmMobile.setCurrentStatus("Conectando a servidores...");
                    Thread.sleep(800);
                    gsmMobile.setCurrentMessage("Subiendo datos a servidor...");
                    Thread.sleep(800);
                    gsmMobile.setCurrentMessage("Intentando enviar datos por internet...");
                    // Send the captured info throughout internet
                    System.out.println("Sending...");
                    gsmMobile.sendDataOverInternet(dataFrame);
                    gsmMobile.setCurrentMessage("Internet: Listo...");

                    //gsmMobile.setStopVisible(true);
                    //gsmMobile.setCurrentMessage("Running... waiting for read...");
                    gsmMobile.setCurrentMessage("Finalizado. [" + datetime + "]");
                    //gsmMobile.repaintNow();
                    System.out.println("Finalizado [" + datetime + "]...");
                }
                
                time = null;
                //if(isTimeToReset) Vm.exitAndReboot(); //ESTE COMANDO REINICIA EL APLICATIVO
            } catch(Exception ex) {
                ex.printStackTrace();
                System.out.println("Dispositivo: "+device.getName());
                if(i<devices.length) {
                    System.out.println("dataFrame: "+dataFrame[i]);
                    System.out.println("dataFrame.length: "+dataFrame[i].length());
                }//end if
            }//end try-catch
        //}//end if(running)
        }//end while(running)
    }//end run()

    public void start() {
    //gsmMobile.setConnectionStatus(true);
    gsmMobile.setCurrentStatus("Ejecutando... esperando lectura...");  
    gsmMobile.monitoreo = new Thread(this);
    //MainWindow.getMainWindow().addThread(modbusManager, false);
    this.setRunning();
    gsmMobile.monitoreo.start();
    }

    public void stop() {
        running = false;
        //gsmMobile.setConnectionStatus(false);
        gsmMobile.clearText();
        this.stopped();
        gsmMobile.setCurrentStatus("Monitoreo finalizado");
    }

    private void initializeCOMPort(Configuration configuration) throws Exception {
    	
        int comPort = Integer.parseInt(configuration.getComPort());
    	int baudRate = 4800;
        int dataBits = 8;
        boolean parity = SerialPort.PARITY_NONE;
        int stopBits = 2;
        serialPort = new SerialPort(comPort, baudRate, dataBits, parity, stopBits);
    }

    public void stopped() {
        try {
            //10. Close the connection
            serialPort.close();
            dmd.releaseInstance();
        } catch(Exception ex) {
            if(dmd.isValid()) dmd.releaseInstance();
            if(serialPort.isOpen()) serialPort=null;
        }
    }
}